package com.zh.yqbj.service.impl;


import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zh.yqbj.constant.DefalutUserConstant;
import com.zh.yqbj.dto.*;
import com.zh.yqbj.entity.UserRole;
import com.zh.yqbj.exception.accountExcption.*;
import com.zh.yqbj.VO.LoginVO;
import com.zh.yqbj.VO.UserVO;
import com.zh.yqbj.annotation.OperationLog;
import com.zh.yqbj.constant.CaptchaConstant;
import com.zh.yqbj.constant.OperationConstant;
import com.zh.yqbj.entity.User;
import com.zh.yqbj.enums.OperationType;
import com.zh.yqbj.service.AccountService;
import com.zh.yqbj.service.RoleService;
import com.zh.yqbj.service.UserRoleService;
import com.zh.yqbj.service.UserService;
import com.zh.yqbj.util.CodeUtil;
import com.zh.yqbj.util.EmailUtil;
import com.zh.yqbj.util.SMSUtil;
import com.zh.yqbj.util.ValidationUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.MessagingException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


@Slf4j
@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private UserService userService;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private EmailUtil emailUtil;
    @Autowired
    private SMSUtil smsUtil;
    @Autowired
    private ValidationUtil validationUtil;

    @Autowired
    private CodeUtil codeUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog(value = OperationConstant.OPERATION_LOGIN, type = OperationType.OFFLINE)
    public LoginVO userLogin(UserLoginDTO userLoginDTO) throws UnknownAccountException, ErrorPasswordException,
            ErrorCodeException, RregisterException {
        //0. 根据传入的对象确定是账密登录，邮箱登录，手机号登录 暂时没有获取角色
        String username = userLoginDTO.getUsername();
        String email = userLoginDTO.getEmail();
        String phone = userLoginDTO.getPhone();
        LoginVO loginVO;
        //0.5 获取自身代理
        AccountService accountServiceProxy = (AccountService) AopContext.currentProxy();
        //1. 账密登录
        if (StrUtil.isNotEmpty(username)) {
            loginVO = this.loginByUsername(userLoginDTO);
        }
        // 2. 验证邮箱格式是否正确
        else if (StrUtil.isNotEmpty(email)) {
            loginVO = accountServiceProxy.loginByEmail(userLoginDTO);
        }
        // 3. 验证手机号格式是否正确
        else if (StrUtil.isNotEmpty(phone)) {
            loginVO = accountServiceProxy.loginByPhone(userLoginDTO);
        } else {
            throw new UnknownAccountException("账号不存在");
        }
        if (StrUtil.isNotEmpty(StpUtil.getLoginIdAsString())) {

            log.info("角色:{}", StpUtil.getRoleList(StpUtil.getLoginId()));
        }
        return loginVO;
    }


    @Override
    @Transactional(rollbackFor = {Exception.class})
//    @OperationLog(value = OperationConstant.OPERATION_LOGIN, type = OperationType.ONLINE)
    public LoginVO loginByUsername(UserLoginDTO userLoginDTO) throws UnknownAccountException, ErrorPasswordException {
        UserVO userVO = new UserVO();
        LoginVO loginVO = new LoginVO();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        //1. 验证账号是否存在
        queryWrapper.eq(User::getUsername, userLoginDTO.getUsername());
        User user = userService.getOne(queryWrapper);
        if (Objects.isNull(user)) {
            throw new UnknownAccountException();
        }
        if (StrUtil.isNotEmpty(user.getUsername())) {
            //2. 验证密码是否正确
            String comparePwd = SaSecureUtil.sha1(userLoginDTO.getPassword());
            String oldPwd = user.getPassword();
            if (StrUtil.equals(oldPwd, comparePwd)) {

//                登录成功
                StpUtil.login(user.getId(), SaLoginConfig.setExtra("userId", user.getId()));
                SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
                BeanUtil.copyProperties(user, userVO);
                loginVO.setUserVO(userVO);
                loginVO.setToken(tokenInfo.getTokenValue());
            } else {
                //密码错误
                throw new ErrorPasswordException();
            }
        } else {
            // 账号不存在
            throw new UnknownAccountException();
        }
        return loginVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginVO loginByEmail(UserLoginDTO userLoginDTO) throws ErrorCodeException, RregisterException {
        //0. 检验验证码
        String imageBase64 = userLoginDTO.getImageBase64();
        String code = userLoginDTO.getCode();
        boolean checkSuccess = validationUtil.codeCheck(imageBase64, code, CaptchaConstant.CAPTCHA_EMAIL_KEY);
        //校验没通过
        if (!checkSuccess) {
            throw new ErrorCodeException();
        }
        //1. 验证邮箱账号是否存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, userLoginDTO.getEmail());
        User user = userService.getOne(queryWrapper);
        // 1.1不存在则注册并登录，存在直接登录
        if (Objects.isNull(user)) {
            user = new User();
            user.setNickname(RandomUtil.randomString(userLoginDTO.getEmail(), 16));
            user.setEmail(userLoginDTO.getEmail());
            user.setAvatar(DefalutUserConstant.DEFAULT_USER_AVATAR);
            user.setCreateTime(DateTime.now().toLocalDateTime());
            user.setUpdateTime(DateTime.now().toLocalDateTime());
            userService.save(user);
            User one = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getEmail, userLoginDTO.getEmail()));
            if (Objects.isNull(one)) {
                throw new RregisterException();
            }
            //设置角色
            UserRole userRole = new UserRole();
            userRole.setUserId(one.getId());
            userRole.setRoleId("1");
            userRoleService.save(userRole);
        }
        // 2. 登录
        UserVO userVO = new UserVO();
        LoginVO loginVO = new LoginVO();
        StpUtil.login(user.getId(), SaLoginConfig.setExtra("userId", user.getId()));
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        BeanUtil.copyProperties(user, userVO);
        loginVO.setUserVO(userVO);
        loginVO.setToken(tokenInfo.getTokenValue());
        return loginVO;

    }

    @Override
//    @Transactional(rollbackFor = Exception.class)
    public LoginVO loginByPhone(UserLoginDTO userLoginDTO) throws ErrorCodeException, RregisterException {
        //0.校验验证码
        String imageBase64 = userLoginDTO.getImageBase64();
        String code = userLoginDTO.getCode();
        boolean checkSuccess = validationUtil.codeCheck(imageBase64, code, CaptchaConstant.CAPTCHA_PHONE_KEY);
        if (!checkSuccess) {
            throw new ErrorCodeException();
        }
        //1. 该手机号账号是否存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, userLoginDTO.getPhone());
        User user = userService.getOne(queryWrapper);
        //1.1 不存在 注册登录，存在直接登录
        if (Objects.isNull(user)) {
            user = new User();
            user.setNickname(RandomUtil.randomString(userLoginDTO.getPhone(), 16));
            user.setPhone(userLoginDTO.getPhone());
            user.setAvatar(DefalutUserConstant.DEFAULT_USER_AVATAR);
            user.setCreateTime(DateTime.now().toLocalDateTime());
            user.setUpdateTime(DateTime.now().toLocalDateTime());
            userService.save(user);
            User one = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, userLoginDTO.getPhone()));
            if (Objects.isNull(one)) {
                throw new RregisterException();
            }
            //设置角色
            UserRole userRole = new UserRole();
            userRole.setUserId(one.getId());
            userRole.setRoleId("1");
            userRoleService.save(userRole);
        }
        // 2. 登录
        UserVO userVO = new UserVO();
        LoginVO loginVO = new LoginVO();
        StpUtil.login(user.getId(), SaLoginConfig.setExtra("userId", user.getId()));
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        BeanUtil.copyProperties(user, userVO);
        loginVO.setUserVO(userVO);
        loginVO.setToken(tokenInfo.getTokenValue());
        return loginVO;

    }

    @Override
    @OperationLog(value = OperationConstant.OPERATION_LOGOUT, type = OperationType.ONLINE)
    public void userLogout() {
        StpUtil.logout();
    }

    @Override
    public String sendCode(SendCodeDTO sendCodeDTO) throws MessagingException, UnsupportedEncodingException,
            NoMoneyException {
        String phone;
        String email;
        if (!Objects.isNull(sendCodeDTO)) {
            phone = sendCodeDTO.getPhone();
            email = sendCodeDTO.getEmail();

            boolean isPhone = validationUtil.isPhone(phone);
            boolean isEmail = validationUtil.isEmail(email);
            if (isPhone) {
                //1. 发送短信
                return this.sendCodeByPhone(phone);
            }
            if (isEmail) {
                // 2.发送邮箱
                return this.sendCodeByEmail(email);
            }
        }
        // 3. 发送原始验证码
        return this.sendCodeOriginal();

    }


    /**
     * 原始验证码发送
     *
     * @return 验证码的base64
     */
    private String sendCodeOriginal() {
        //0. 获取验证码
        List<String> codeList = codeUtil.getCode();
        String imageBase64 = codeList.get(0);
        String code = codeList.get(1);
        redisTemplate.opsForValue().set(CaptchaConstant.CAPTCHA_CODE_KEY + imageBase64, code,
                CaptchaConstant.CAPTCHA_EXPIRE_TIME, TimeUnit.SECONDS);
        return imageBase64;
    }

    /**
     * 邮箱发送验证码
     *
     * @param to 目的邮箱
     * @return key
     * @throws MessagingException           error
     * @throws UnsupportedEncodingException error
     */
    @Override
    public String sendCodeByEmail(String to) throws MessagingException, UnsupportedEncodingException {
        //0. 发送验证码
        List<String> codeList = codeUtil.getCode();
        String imageBase64 = codeList.get(0);
        String code = codeList.get(1);
        String context = "您的验证码是：" + code + "，5分钟内有效。";
        emailUtil.sendEmail(to, "验证码", context);
        redisTemplate.opsForValue().set(CaptchaConstant.CAPTCHA_EMAIL_KEY + imageBase64, code,
                CaptchaConstant.CAPTCHA_EXPIRE_TIME, TimeUnit.SECONDS);
        return imageBase64;
    }

    @Override
    public String sendCodeByPhone(@NotNull String phone) throws NoMoneyException {
        // 短信验证码只能是4-6位数字
        // hutool 生成仅数字验证码
        String imageBase64 = RandomUtil.randomString(64);
        int code = Integer.parseInt(RandomUtil.randomNumbers(4));
        // 发送要钱，先不开启
//        boolean isSend = smsUtil.sendSms(phone, code);
//        if (!isSend) {
//            throw new NoMoneyException();
//        }
        log.info("您的验证码为 ${} ，5分钟内有效，请及时使用。", code);
        redisTemplate.opsForValue().set(CaptchaConstant.CAPTCHA_PHONE_KEY + imageBase64, String.valueOf(code),
                CaptchaConstant.CAPTCHA_EXPIRE_TIME, TimeUnit.SECONDS);
        return imageBase64;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog(value = OperationConstant.OPERATION_REGISTER, type = OperationType.OFFLINE)
    public void userRegister(UserRegisterDTO userRegisterDTO) throws ErrorUsernamePatternException,
            ErrorRepasswordException, RregisterException, DuplicateAccountException, ErrorCodeException {
        //1. 判空
        String username = userRegisterDTO.getUsername();
        String password = userRegisterDTO.getPassword();
        String rePassword = userRegisterDTO.getRePassword();
        String imageBase64 = userRegisterDTO.getImageBase64();
        String code = userRegisterDTO.getCode();
        //0. 叫验证码
        boolean codeCheck = validationUtil.codeCheck(imageBase64, code, CaptchaConstant.CAPTCHA_CODE_KEY);
        if (!codeCheck) {
            throw new ErrorCodeException();
        }
        //1. 校验 账号格式
        if (!validationUtil.greatUsername(username)) {
            throw new ErrorUsernamePatternException();
        }
        //2. 查重
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        User one = userService.getOne(queryWrapper);
        if (!Objects.isNull(one)) {
            throw new DuplicateAccountException();
        }
        //3. 验证两次密码输入
        String oPwd = SaSecureUtil.sha1(password);
        String rPwd = SaSecureUtil.sha1(rePassword);
        if (!StrUtil.equals(oPwd, rPwd)) {
            throw new ErrorRepasswordException();
        }
        //4. 成功 构建User对象
        User user = new User();
        user.setUsername(username);
        user.setPassword(oPwd);
        user.setNickname(username);
        user.setCreateTime(DateTime.now().toLocalDateTime());
        user.setUpdateTime(DateTime.now().toLocalDateTime());
        userService.save(user);
        User saveOne = userService.getOne(queryWrapper);
//        再判一次空
        if (Objects.isNull(saveOne)) {
            throw new RregisterException();
        }
        //角色赋予
        UserRole userRole = new UserRole();
        userRole.setUserId(saveOne.getId());
        userRole.setRoleId("1");
        userRoleService.save(userRole);
        //5. 注册成功

    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public String bindingEmail(BindEmailDTO bindEmailDTO) throws ErrorCodeException, DuplicateEmailException,
            ErrorEmailPatternException {
        // 校验验证码
        String imageBase64 = bindEmailDTO.getImageBase64();
        String code = bindEmailDTO.getCode();
        String email = bindEmailDTO.getEmail();
        String userId = (String) StpUtil.getLoginId();
        boolean codeCheck = validationUtil.codeCheck(imageBase64, code, CaptchaConstant.CAPTCHA_EMAIL_KEY);
        if (!codeCheck) {
            throw new ErrorCodeException();
        }
        //根据是否传入了email判断绑定还是解绑
        if (StrUtil.isBlank(email)) {
            // 解绑
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getId, userId);
            updateWrapper.set(User::getEmail, null);
            userService.update(null, updateWrapper);
            return "解绑成功";
        }
        // 校验邮箱
        boolean isEmail = validationUtil.isEmail(email);
        if (!isEmail) {
            throw new ErrorEmailPatternException();
        }
        // 校验邮箱是已绑定
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, email);
        User one = userService.getOne(queryWrapper);
        if (!Objects.isNull(one)) {
            throw new DuplicateEmailException();
        }
        // 绑定邮箱
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId);
        updateWrapper.set(User::getEmail, email);
        userService.update(null, updateWrapper);
        return "绑定成功";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String bindingPhone(BindPhoneDTO bindPhoneDTO) throws ErrorCodeException,
            ErrorPhonePatternException, DuplicatePhoneException {
        // 校验验证码
        String imageBase64 = bindPhoneDTO.getImageBase64();
        String code = bindPhoneDTO.getCode();
        String phone = bindPhoneDTO.getPhone();
        String userId = (String) StpUtil.getLoginId();
        boolean codeCheck = validationUtil.codeCheck(imageBase64, code, CaptchaConstant.CAPTCHA_PHONE_KEY);
        if (!codeCheck) {
            throw new ErrorCodeException();
        }
        // 根据是否传入了手机号判断解绑还是绑定
        if (StrUtil.isBlank(phone)) {
            // 解绑
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getId, userId);
            updateWrapper.set(User::getPhone, null);
            userService.update(null, updateWrapper);
            return "解绑成功";
        }
        // 校验手机号
        boolean isPhone = validationUtil.isPhone(phone);
        if (!isPhone) {
            throw new ErrorPhonePatternException();
        }
        // 校验手机号是否已绑定
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, phone);
        User one = userService.getOne(queryWrapper);
        if (!Objects.isNull(one)) {
            throw new DuplicatePhoneException();
        }
        // 绑定手机号
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId);
        updateWrapper.set(User::getPhone, phone);
        userService.update(null, updateWrapper);
        return "绑定成功";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String updateUser(UserUpdateDTO userUpdateDTO) throws ErrorCodeException, ErrorPhonePatternException,
            ErrorEmailPatternException, ErrorUsernamePatternException, ErrorRepasswordException,
            DuplicateAccountException, DuplicatePhoneException, DuplicateEmailException {
        //1.传递了username ,password,rePassword,phone/email 则说明是完善账号信息
        String username = userUpdateDTO.getUsername();
        String password = userUpdateDTO.getPassword();
        String rePassword = userUpdateDTO.getRePassword();
        //2. 前面我们规定过，服务内方法调用走代理,即使这里没有AOP方法
        AccountService accountServiceProxy = (AccountService) AopContext.currentProxy();
        if (StrUtil.isEmpty(username) || StrUtil.isEmpty(password) || StrUtil.isEmpty(rePassword)) {
            //3. 说明不是完善账号,其他的直接修改
            return accountServiceProxy.updateInfo(userUpdateDTO);
        }
        //4.判断是通过email/phone创建的账号
        String phone = userUpdateDTO.getPhone();
        String email = userUpdateDTO.getEmail();
        String imageBase64 = userUpdateDTO.getImageBase64();
        String code = userUpdateDTO.getCode();
        String newPwd = SaSecureUtil.sha1(password);
        //5. 常规校验，正常程序流程不会触发,除非跳过前端直接请求接口
        boolean goodUsername = validationUtil.greatUsername(username);
        if (!goodUsername) {
            throw new ErrorUsernamePatternException();
        }
        if (!StrUtil.equals(password, rePassword)) {
            throw new ErrorRepasswordException();
        }

        if (StrUtil.isNotEmpty(phone)) {
            //6.说明是手机号创建的账号
            return accountServiceProxy.completeByPhone(phone, username, newPwd, imageBase64, code);
        }
        if (StrUtil.isNotEmpty(email)) {
            //7.说明是邮箱创建的账号
            return accountServiceProxy.completeByEmail(email, username, newPwd, imageBase64, code);
        }
        return "我不会被打印出来了吧~ AccountServiceImpl updateUser";
    }

    @Transactional(rollbackFor = Exception.class)
    @NotNull
    public String updateInfo(UserUpdateDTO userUpdateDTO) {

        User user = BeanUtil.copyProperties(userUpdateDTO, User.class);
        String userId = StpUtil.getLoginIdAsString();
        user.setId(userId);
        // 加层保险确保email,phone不会被修改
        user.setEmail(null);
        user.setPhone(null);
        user.setUpdateTime(LocalDateTimeUtil.now());
        userService.updateById(user);
        return "修改成功";
    }

    @Override
    public String refundPwd(RefundPwdDTO refundPwdDTO) throws ErrorCodeException, ErrorPhonePatternException,
            UnBindingPhoneException, UnknownAccountException, ErrorEmailPatternException, UnBindingEamilException {
        String username = refundPwdDTO.getUsername();
        String code = refundPwdDTO.getCode();
        String imageBse64 = refundPwdDTO.getImageBase64();
        String phone = refundPwdDTO.getPhone();
        String email = refundPwdDTO.getEmail();
        //0. 账号是否正确
        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        if (Objects.isNull(user)) {
            throw new UnknownAccountException();
        }
        if (StrUtil.isNotEmpty(phone)) {
            //1.说明是手机创建的账号
            boolean codeCheck = validationUtil.codeCheck(imageBse64, code, CaptchaConstant.CAPTCHA_PHONE_KEY);
            if (!codeCheck) {
                throw new ErrorCodeException();
            }
            boolean isPhone = validationUtil.isPhone(phone);
            if (!isPhone) {
                throw new ErrorPhonePatternException();
            }
            //2.验证手机，这个手机号没有绑定过账号
            User one = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
            if (Objects.isNull(one)) {
                throw new UnBindingPhoneException();
            }
            if (StrUtil.isEmpty(one.getUsername()) || StrUtil.isEmpty(one.getPassword())) {
                throw new UnknownAccountException();
            }
            // 手机号绑定的不是这个账号
            if (StrUtil.isNotEmpty(username) && !StrUtil.equals(one.getUsername(), username)) {
                throw new UnknownAccountException();
            }
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getPhone, phone);
            updateWrapper.set(User::getPassword, SaSecureUtil.sha1(DefalutUserConstant.DEFAULT_USER_PASSWORD));
            userService.update(null, updateWrapper);
            return "密码重置为123456,请及时修改密码";
        }
        if (StrUtil.isNotEmpty(email)) {
            //说明是邮箱创建的账号
            boolean codeCheck = validationUtil.codeCheck(imageBse64, code, CaptchaConstant.CAPTCHA_EMAIL_KEY);
            //验证验证码
            if (!codeCheck) {
                throw new ErrorCodeException();
            }
            boolean isEmail = validationUtil.isEmail(email);
            if (!isEmail) {
                throw new ErrorEmailPatternException();
            }
            //验证邮箱,邮箱没有绑定过账号
            User one = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getEmail, email));
            if (Objects.isNull(one)) {
                throw new UnBindingEamilException();
            }
            if (StrUtil.isEmpty(one.getUsername()) || StrUtil.isEmpty(one.getPassword())) {
                throw new UnknownAccountException();
            }
            //  邮箱绑定的不是这个账号
            if (StrUtil.isNotEmpty(username) && !StrUtil.equals(one.getUsername(), username)) {
                throw new UnknownAccountException();
            }
            //修改密码
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getEmail, email);
            updateWrapper.set(User::getPassword, SaSecureUtil.sha1(DefalutUserConstant.DEFAULT_USER_PASSWORD));
            userService.update(null, updateWrapper);
            return "密码重置为123456,请及时修改密码";
        }
        return "遇到我你算是遇到bug了";
    }

    @Override
    @SaCheckLogin
    @OperationLog(value = "修改密码", type = OperationType.ONLINE)
    public void updatePwd(UpdatePwdDTO updatePwdDTO) throws UnknownAccountException, ErrorPasswordException,
            ErrorRepasswordException, ErrorCodeException {
        String username = updatePwdDTO.getUsername();
        String oldPassword = updatePwdDTO.getOldPassword();
        String newPassword = updatePwdDTO.getNewPassword();
        String rePassword = updatePwdDTO.getRePassword();
        String imageBase64 = updatePwdDTO.getImageBase64();
        String code = updatePwdDTO.getCode();
        //1.校验验证码
        boolean codeCheck = validationUtil.codeCheck(imageBase64, code, CaptchaConstant.CAPTCHA_CODE_KEY);
        if (!codeCheck) {
            throw new ErrorCodeException();
        }
        //2. 校验输入账号是否为本人账号
        String loginId = (String) StpUtil.getLoginId();
        User user = userService.getById(loginId);
        if (!StrUtil.equals(user.getUsername(), username)) {
            throw new UnknownAccountException();
        }
        //3. 校验输入旧密码是否正确
        if (!StrUtil.equals(user.getPassword(), SaSecureUtil.sha1(oldPassword))) {
            throw new ErrorPasswordException();
        }
        //4. 校验输入新密码 两次是否一致
        if (!StrUtil.equals(SaSecureUtil.sha1(newPassword), SaSecureUtil.sha1(rePassword))) {
            throw new ErrorRepasswordException();
        }
        //5. 校验通过，修改密码
        User newUser = new User();
        newUser.setId((String) StpUtil.getLoginId());
        newUser.setPassword(SaSecureUtil.sha1(newPassword));
        newUser.setUpdateTime(LocalDateTimeUtil.now());
        userService.updateById(newUser);
        //6. 修改之后退出登录
        StpUtil.logout(StpUtil.getLoginId());
    }

    @Transactional(rollbackFor = Exception.class)
    @NotNull
    public String completeByPhone(String phone, String username, String newPwd, String imageBase64, String code) throws ErrorPhonePatternException,
            ErrorCodeException, DuplicatePhoneException {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        boolean codeCheck = validationUtil.codeCheck(imageBase64, code, CaptchaConstant.CAPTCHA_PHONE_KEY);
        if (!codeCheck) {
            throw new ErrorCodeException();
        }
        User one = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
        if (!Objects.isNull(one)) {
            throw new DuplicatePhoneException();
        }
        boolean isPhone = validationUtil.isPhone(phone);
        if (!isPhone) {
            throw new ErrorPhonePatternException();
        }

        updateWrapper.eq(User::getPhone, phone);
        updateWrapper.set(User::getUsername, username);
        updateWrapper.set(User::getPassword, newPwd);
        updateWrapper.set(User::getUpdateTime, LocalDateTimeUtil.now());
        userService.update(null, updateWrapper);
        return "完善账号成功，请重新登录";
    }

    @Transactional(rollbackFor = Exception.class)
    @NotNull
    public String completeByEmail(String email, String username, String newPwd, String imageBase64, String code) throws ErrorEmailPatternException, ErrorCodeException, DuplicateEmailException {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        boolean codeCheck = validationUtil.codeCheck(imageBase64, code, CaptchaConstant.CAPTCHA_EMAIL_KEY);
        if (!codeCheck) {
            throw new ErrorCodeException();
        }
        User one = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getEmail, email));
        if (!Objects.isNull(one)) {
            throw new DuplicateEmailException();
        }
        boolean isEmail = validationUtil.isEmail(email);
        if (!isEmail) {
            throw new ErrorEmailPatternException();
        }
        updateWrapper.eq(User::getEmail, email);
        updateWrapper.set(User::getUsername, username);
        updateWrapper.set(User::getPassword, newPwd);
        updateWrapper.set(User::getUpdateTime, LocalDateTimeUtil.now());
        userService.update(null, updateWrapper);
        return "完善账号成功，请重新登录";
    }
}
